﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace CNative
{
    public static partial class Utils
    {
        /// <summary>
        /// 数据替换
        /// 注：支持一次性替换多个，支持所有可迭代类型，KeyValuePair键值对中Key为需要替换的数据，Value为替换后数据
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="parttern">替换模式</param>
        /// <returns></returns>
        public static IEnumerable<T> Replace<T>(this IEnumerable<T> source, params KeyValuePair<IEnumerable<T>, IEnumerable<T>>[] parttern)
        {
            List<T> resList = new List<T>();
            List<T> sourceList = source.ToList();
            for (int i = 0; i < sourceList.Count; i++)
            {
                bool replaced = false;
                parttern.ForEach(aMatch =>
                {
                    var oldvalue = aMatch.Key.ToList();
                    var newvalue = aMatch.Value.ToList();

                    bool needReplace = true;
                    for (int j = 0; j < oldvalue.Count; j++)
                    {
                        if (!sourceList[i + j].Equals(oldvalue[j]))
                            needReplace = false;
                    }
                    if (needReplace)
                    {
                        resList.AddRange(newvalue);
                        i = i + oldvalue.Count - 1;
                        replaced = true;
                    }
                });
                if (!replaced)
                    resList.Add(sourceList[i]);
            }

            return resList;
        }

        /// <summary>
        /// 复制序列中的数据
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="iEnumberable">原数据</param>
        /// <param name="startIndex">原数据开始复制的起始位置</param>
        /// <param name="length">需要复制的数据长度</param>
        /// <returns></returns>
        public static IEnumerable<T> Copy<T>(this IEnumerable<T> iEnumberable, int startIndex, int length)
        {
            var sourceArray = iEnumberable.ToArray();
            T[] newArray = new T[length];
            Array.Copy(sourceArray, startIndex, newArray, 0, length);

            return newArray;
        }

        /// <summary>
        /// 序列连接对象
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="iEnumberable">原序列</param>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static IEnumerable<T> Concat<T>(this IEnumerable<T> iEnumberable, T obj)
        {
            return iEnumberable.Concat(new T[] { obj });
        }

        /// <summary>
        /// 给IEnumerable拓展ForEach方法
        /// </summary>
        /// <typeparam name="T">模型类</typeparam>
        /// <param name="iEnumberable">数据源</param>
        /// <param name="func">方法</param>
        public static void ForEach<T>(this IEnumerable<T> iEnumberable, Action<T> func)
        {
            foreach (var item in iEnumberable)
            {
                func(item);
            }
        }

        /// <summary>
        /// 给IEnumerable拓展ForEach方法
        /// </summary>
        /// <typeparam name="T">模型类</typeparam>
        /// <param name="iEnumberable">数据源</param>
        /// <param name="func">方法</param>
        public static void ForEach<T>(this IEnumerable<T> iEnumberable, Action<T, int> func)
        {
            var array = iEnumberable.ToArray();
            for (int i = 0; i < array.Count(); i++)
            {
                func(array[i], i);
            }
        }

        /// <summary>
        /// IEnumerable转换为List'T'
        /// </summary>
        /// <typeparam name="T">参数</typeparam>
        /// <param name="source">数据源</param>
        /// <returns></returns>
        public static List<T> CastToList<T>(this IEnumerable source)
        {
            return new List<T>(source.Cast<T>());
        }
        /// <summary>
        /// T[]转换为分段List( List'ArraySegment'T'')
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="segmentCapacity">分段ArraySegment新列表最初可以存储的元素数</param>
        /// <returns></returns>
        public static List<ArraySegment<T>> ToListSegment<T>(this T[] source, int segmentCapacity)
        {
            if (segmentCapacity < 2) segmentCapacity = source.Length;
            var segmentCount = 0;
            if (source.Length % segmentCapacity == 0)
            { segmentCount = source.Length / segmentCapacity; }
            else
            { segmentCount = (source.Length / segmentCapacity) + 1; }
            var resList = new List<ArraySegment<T>>();
            for (int i = 0; i < segmentCount; i++)
            {
                var _Count = Math.Min(source.Length - segmentCapacity * (i), segmentCapacity);

                resList.Add(new ArraySegment<T>(source, i * segmentCapacity, _Count));
            }
            return resList;
        }
        /// <summary>
        /// IEnumerable转换为分段List( List'ArraySegment'T'')
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="segmentCapacity">分段ArraySegment新列表最初可以存储的元素数</param>
        /// <returns></returns>
        public static List<ArraySegment<T>> ToListSegment<T>(this IEnumerable<T> source, int segmentCapacity)
        {
            return source.ToArray().ToListSegment(segmentCapacity);
        }
        public static bool Remove<TKey, TValue>(this IDictionary<TKey, TValue> source, TKey key, out TValue val)
        {
            val = default(TValue);
            if (source?.ContainsKey(key) == false) return false;
            if (source.TryGetValue(key, out val))
            {
                source.Remove(key);
                return true;
            }
            return false;
        }
        public static TValue GetValueOrDefault<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> source, TKey key)
        {
            var val = default(TValue);
            if (source?.ContainsKey(key) == false) return val;
            if (source.TryGetValue(key, out val))
            {
                return val;
            }
            return val;
        }


        static Random Random = new Random();
        /// <summary>
        /// 获取集合随机下标
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ts"></param>
        /// <returns></returns>
        public static int GetRandomIndex<T>(this IEnumerable<T> ts)
        {
            if (ts.IsNullOrEmpty_()) return 0;
            int maxValue = ts.Count();
            var num = Random.Next(0, maxValue);
            while (num < 0 || num >= maxValue)
            {
                num = Random.Next(0, maxValue);
            }
            return num;
        }
    }
}
